import fg from "fast-glob";
import fs from "fs-extra";
import path from "path";
import { UnityHelper } from "./UnityHelper.js";
import { PrefabSearcher } from "./PrefabSearcher.js";
import { toolchain } from "../toolchain.js";

export class UsageFinder {
    public async lookUp(input: string): Promise<void> {
        input = path.isAbsolute(input) ? input : path.join(toolchain.opts.projectRoot, input);
        const inputStat = await fs.stat(input);
        let inputMetas: string[];
        if (inputStat.isFile()) {
            inputMetas = [input + '.meta'];
        } else {
            const files = await fg('**/*.meta', { cwd: input });
            inputMetas = files.map((v) => path.join(input, v));
        }

        const guids: string[] = [];
        const guidMap: { [meta: string]: string } = {};
        for (const m of inputMetas) {
            const guid = await UnityHelper.readGUID(m);
            guids.push(guid);
            guidMap[m] = guid;
        }
        
        if (toolchain.opts.target && toolchain.opts.target.endsWith('.prefab')) {
            const f = path.join(toolchain.opts.projectRoot, toolchain.opts.target);
            await this.lookUpImageInUI(f, guids);
        } else {
            const usageMap: { [file: string]: { f: string, hit: number }[] } = {};
            const targets = toolchain.opts.target ? [toolchain.opts.target] : await fg(UnityHelper.CompositeFileTypes.map((v) => `**/*${v}`), { cwd: toolchain.opts.projectRoot });
            for (const target of targets) {
                const f = path.join(toolchain.opts.projectRoot, target);
                const content = await fs.readFile(f, 'utf-8');
                for (const meta in guidMap) {
                    const mchs = content.match(new RegExp(`guid: ${guidMap[meta]}`, 'g'));
                    if (mchs && mchs.length > 0) {
                        const file = meta.replace('.meta', '');
                        let arr = usageMap[file];
                        if (arr == null) usageMap[file] = arr = [];
                        arr.push({ f, hit: mchs.length });
                    }
                }
            }

            for (const file in usageMap) {
                const arr = usageMap[file];
                console.log('Usage of: ', file, ' --> ', guidMap[file + '.meta']);
                console.log('-------------------');

                if (arr.every((v) => v.f.endsWith('.prefab'))) {
                    for (const u of arr) {
                        if (file.endsWith('.png') || file.endsWith('.jpg') || file.endsWith('.tga')) {
                            await this.lookUpImageInUI(u.f, [guidMap[file + '.meta']]);
                        } else {
                            await this.lookUpScriptInUI(u.f, [guidMap[file + '.meta']]);
                        }
                    }
                } else {
                    for (const u of arr) {
                        console.log(u.f.replaceAll('\\', '/') + ', hit: ' + u.hit);
                    }
                }
                console.log('');
            }
        }
    }

    private async lookUpImageInUI(prefabFile: string, guids: string[]): Promise<void> {
        console.log(prefabFile.replaceAll('\\', '/'));
        const searcher = new PrefabSearcher();
        const usages = await searcher.findImageUsages(prefabFile, guids);
        for (const u of usages) {
            console.log(u.path.replaceAll('\\', '/'));
        }
        console.log('');
    }

    private async lookUpScriptInUI(prefabFile: string, guids: string[]): Promise<void> {
        console.log(prefabFile.replaceAll('\\', '/'));
        const searcher = new PrefabSearcher();
        const usages = await searcher.findScriptUsages(prefabFile, guids);
        for (const u of usages) {
            console.log(u.path.replaceAll('\\', '/'));
        }
        console.log('');
    }
}
